		TITLE	LINMAP - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SEGMENTS
		INCLUDE	MODULES
if	fg_pe
		INCLUDE	PE_STRUC
endif

		PUBLIC	ALLOW_LINNUMS_MAP,DO_LINENUMBERS_MAP


		.DATA

		EXTERNDEF	XOUTBUF:BYTE

		EXTERNDEF	CURNMOD_GINDEX:DWORD,FIRST_MODULE_GINDEX:DWORD

		EXTERNDEF	MAPLINES_OK_SEM:GLOBALSEM_STRUCT,MODULE_GARRAY:STD_PTR_S,SRC_GARRAY:STD_PTR_S,MDB_GARRAY:STD_PTR_S
		EXTERNDEF	SEGMOD_GARRAY:STD_PTR_S,CSEG_GARRAY:STD_PTR_S,PE_OBJECT_GARRAY:STD_PTR_S,SEGMENT_GARRAY:STD_PTR_S


		.CODE	PASS2_TEXT

		EXTERNDEF	_capture_eax:proc
		EXTERNDEF	_release_eax:proc
		EXTERNDEF	_release_eax_bump:proc
		EXTERNDEF	HEXWOUT:PROC,RELEASE_SEGMENT:PROC,LINE_OUT:PROC,HEADER_OUT:PROC,MOVE_ASCIZ_ESI_EDI:PROC,MOVEIT:PROC
		EXTERNDEF	_move_file_list_gindex_path_prim_ext:proc,OBJ_PHASE:PROC,CAPTURE_EAX:PROC,RELEASE_EAX:PROC
		EXTERNDEF	SAY_VERBOSE:PROC,UNUSE_MDB_PARRAY:PROC,HEXDWOUT:PROC,MOVE_ESI_EDI_STG:PROC


WM_LINNUM_VARS		STRUC

WM_FRAME_FACTOR_BP	DD	?
WM_SEG_FRAME_BP		DD	?
WM_COUNT_BP		DD	?
WM_LIN_BLK_BP		DD	?
WM_LIN_PHYS_BP		DD	?
WM_CURNMOD_GINDEX_BP	DD	?
WM_CURN_FILE_LIST_GINDEX_BP	DD	?
WM_LAST_SEGMENT_GINDEX_BP	DD	?
WM_LAST_LIN_SRC_GINDEX_BP	DD	?
OFFSET_MASK_BP		DD	?
OFFSET_SIZE_BP		DD	?
WM_BLOCK_BASE_BP	DD	?
WM_LN_STUFF_BP		LINNUM_HEADER_TYPE<>

WM_LINNUM_VARS		ENDS


FIX	MACRO	X

X	EQU	([EBP-SIZE WM_LINNUM_VARS].(X&_BP))

	ENDM


FIX	WM_FRAME_FACTOR
FIX	WM_SEG_FRAME
FIX	WM_COUNT
FIX	WM_LIN_BLK
FIX	WM_LIN_PHYS
FIX	WM_CURNMOD_GINDEX
FIX	WM_CURN_FILE_LIST_GINDEX
FIX	WM_LAST_SEGMENT_GINDEX
FIX	WM_LAST_LIN_SRC_GINDEX
FIX	WM_LN_STUFF
FIX	OFFSET_MASK
FIX	OFFSET_SIZE
FIX	WM_BLOCK_BASE


WM_LN_NEXT_LINNUM	EQU	WM_LN_STUFF._LN_NEXT_LINNUM
WM_LN_BLOCK_BASE	EQU	WM_LN_STUFF._LN_BLOCK_BASE
WM_LN_LENGTH		EQU	WM_LN_STUFF._LN_LENGTH
WM_LN_TYPE		EQU	WM_LN_STUFF._LN_TYPE
WM_LN_SRC_GINDEX	EQU	WM_LN_STUFF._LN_SRC_GINDEX


ALLOW_LINNUMS_MAP	PROC
		;
		;
		;
if	fgh_mapthread
		BITT	_HOST_THREADED
		JZ	DO_LINENUMBERS_MAP

		RELEASE	MAPLINES_OK_SEM

		RET
endif

ALLOW_LINNUMS_MAP	ENDP


DO_LINENUMBERS_MAP	PROC
		;
		;
		;
		BITT	LINENUMBERS_FLAG
		JZ	L9$

		CAPTURE	MAPLINES_OK_SEM		;FOR OPTIMAL LOCALITY

		YIELD				;SO STOP WORKS

		PUSHM	EBP,EDI,ESI,EBX

		MOV	EBP,ESP
		SUB	ESP,SIZE WM_LINNUM_VARS

		ASSUME	EBP:PTR WM_LINNUM_VARS

		MOV	EAX,OFF WRITING_LINNUMS_MSG
		CALL	SAY_VERBOSE

		XOR	EAX,EAX
		MOV	ESI,FIRST_MODULE_GINDEX

		MOV	WM_SEG_FRAME,EAX
		;
		;START AT FIRST MODULE, PRINT LINENUMBERS FOR EACH IF THERE
		;
		MOV	EDI,OFF XOUTBUF

		JMP	TEST_LMOD

L9$:
		RET

WM_LIN_SPEC:
		CALL	WM_GET2

		AND	EAX,0FFFFH
		CALL	SCBTA16

		MOV	EAX,DPTR LIN_FRAME
		MOV	EDX,DPTR LIN_FRAME+4

		MOV	[EDI],EAX
		MOV	[EDI+4],EDX

		ADD	EDI,6
		CALL	WM_GET2			;OFFSET

		AND	EAX,0FFFFH
		MOV	ECX,OFFSET_MASK

		CMP	ECX,-1
		JNZ	LIN16_BIT

		MOV	ECX,EAX
		CALL	WM_GET2

		SHL	EAX,16

		OR	EAX,ECX
		JMP	LIN16_BIT

LCSEGMOD_LOOP:
		;
		;START A NEW SEGMOD
		;
		CALL	LCSEGMOD_START		;DEALS WITH BUNCH OF JUNK

		PUSH	EAX			;NEXT CSEGMOD
		JMP	LCHECK_LINNUM

LLIN_LOOP:
		;
		;START A NEW LINNUM RECORD
		;
		MOV	EAX,ECX
		CALL	LINE_START		;SET UP LINE STUFF, HANDLE CHANGING SRC FILE
LINE_LOOP:
		CMP	ESI,EBX
		JAE	WM_LIN_SPEC

		MOV	EAX,[ESI]
		ADD	ESI,2

		AND	EAX,0FFFFH
		CALL	SCBTA16

		MOV	EAX,DPTR LIN_FRAME
		MOV	EDX,DPTR LIN_FRAME+4

		MOV	[EDI],EAX
		MOV	[EDI+4],EDX

		MOV	EAX,[ESI]		;OFFSET
		MOV	ECX,OFFSET_MASK

		AND	EAX,ECX
		MOV	ECX,OFFSET_SIZE

		ADD	ESI,ECX
		ADD	EDI,6
LIN16_BIT:
		MOV	ECX,WM_FRAME_FACTOR

		ADD	EAX,ECX

		CMP	EAX,64K
		JB	LIN_NOT_32

		CALL	HEXDWOUT
		JMP	WAS_32

LIN_NOT_32:
		CALL	HEXWOUT
WAS_32:
		CMP	EDI,OFF XOUTBUF+64
		JAE	LIN_FLUSH_LINE
NOT_YET:
		DEC	WM_COUNT
		JNZ	LINE_LOOP

		MOV	EAX,WM_BLOCK_BASE

		DEC	DPTR [EAX]
		JNZ	NY_1

		CALL	RELEASE_SEGMENT
NY_1:
		MOV	ECX,WM_LN_NEXT_LINNUM
LCHECK_LINNUM:
		TEST	ECX,ECX
		JNZ	LLIN_LOOP

		POP	EAX
LCHECK_CSEGMOD:
		TEST	EAX,EAX
		JNZ	LCSEGMOD_LOOP
		;
		;NO MORE CODE SEGS THIS MODULE
		;
		CMP	EDI,OFF XOUTBUF
		JZ	NEXT_LMOD

		CALL	LINE_OUT		;FLUSH IF ANY DATA PRESENT
NEXT_LMOD:
		MOV	ESI,WM_CURNMOD_GINDEX
		CONVERT	ESI,ESI,MODULE_GARRAY
		ASSUME	ESI:PTR MODULE_STRUCT

SKIP_MODULE:
		MOV	ESI,[ESI]._M_NEXT_MODULE_GINDEX		;TRY NEXT MODULE

TEST_LMOD:
		MOV	WM_CURNMOD_GINDEX,ESI
if	fgh_mapthread
		GETT	AL,_HOST_THREADED

		OR	AL,AL
		JNZ	NO_CURN_CHG
endif
		MOV	CURNMOD_GINDEX,ESI
NO_CURN_CHG:
		TEST	ESI,ESI
		JZ	LINES_DONE

		CONVERT	ESI,ESI,MODULE_GARRAY
		ASSUME	ESI:PTR MODULE_STRUCT

		MOV	AL,[ESI]._M_FLAGS
		MOV	ECX,[ESI]._M_FILE_LIST_GINDEX

		TEST	AL,MASK M_SRCS_PRESENT
		JZ	SKIP_MODULE

		XOR	EAX,EAX
		MOV	WM_CURN_FILE_LIST_GINDEX,ECX

		MOV	EDX,[ESI]._M_MDB_GINDEX
		MOV	WM_LAST_SEGMENT_GINDEX,EAX

		TEST	EDX,EDX
		JZ	SKIP_MODULE

		CONVERT	EDX,EDX,MDB_GARRAY
		ASSUME	EDX:PTR MDB_STRUCT

		MOV	EAX,[EDX]._MD_FIRST_CSEGMOD_GINDEX	;FIRST CODE SEGMOD
		JMP	LCHECK_CSEGMOD

LIN_FLUSH_LINE:
		CALL	LINE_OUT
		JMP	NOT_YET

LINES_DONE:
		;
if	fgh_mapthread
		BITT	_HOST_THREADED
		JNZ	LINES_DONE_A

		XOR	EAX,EAX
		MOV	CURNMOD_GINDEX,EAX
endif

LINES_DONE_A:

if	debug
;		MOV	AX,SEG FINI_LINNUMS_MSG
		MOV	EAX,OFF FINI_LINNUMS_MSG
		CALL	SAY_VERBOSE
endif

		CALL	UNUSE_MDB_PARRAY

		MOV	ESP,EBP

		POPM	EBX,ESI,EDI,EBP

		RET

DO_LINENUMBERS_MAP	ENDP


WM_GET2		PROC	NEAR
		;
		;GET NEXT TWO BYTES FROM INPUT STREAM
		;
		LEA	EAX,[EBX+6]

		CMP	ESI,EAX
		JE	L1$

		MOV	AX,WPTR [ESI]
		ADD	ESI,2

		RET

L1$:
		MOV	EAX,WM_BLOCK_BASE

		DEC	DPTR [EAX]		;LAST ITEM IN BLOCK?
		MOV	ESI,[EAX+4]

		MOV	WM_BLOCK_BASE,ESI
		JNZ	L2$

		CALL	RELEASE_SEGMENT
L2$:
		LEA	EBX,[ESI + PAGE_SIZE-6]

		MOV	AX,WPTR [ESI+8]
		ADD	ESI,10

		RET

WM_GET2		ENDP


LCSEGMOD_START	PROC	NEAR
		;
		;EAX IS SEGMOD
		;
		;RETURNS WM_FRAME_FACTOR=OFFSET TO ADD TO EACH LINENUMBER
		;	AX IS NEXT CSEGMOD
		;	DSSI IS VIRTUAL LINNUM RECORD ADDRESS
		;
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	EDX,[EAX]._SM_START
		MOV	ECX,[EAX]._SM_MODULE_CSEG_GINDEX

		MOV	EAX,[EAX]._SM_BASE_SEG_GINDEX
		MOV	WM_FRAME_FACTOR,EDX

		CMP	WM_LAST_SEGMENT_GINDEX,EAX
		JZ	L1$

		PUSH	ECX
		CALL	LCSEGMENT_START

		POP	ECX
L1$:
		MOV	EAX,WM_SEG_FRAME
		MOV	EDX,WM_FRAME_FACTOR

		SUB	EDX,EAX
		CONVERT	ECX,ECX,CSEG_GARRAY
		ASSUME	ECX:PTR CSEG_STRUCT
		MOV	EAX,[ECX]._CSEG_NEXT_CSEGMOD_GINDEX

		MOV	WM_FRAME_FACTOR,EDX
		MOV	ECX,[ECX]._CSEG_FIRST_LINNUM

		RET

		ASSUME	EAX:NOTHING,ECX:NOTHING

LCSEGMOD_START	ENDP


LCSEGMENT_START	PROC	NEAR
		;
		;EAX IS NEW SEGMENT_GINDEX
		;
		;DEFINE NEW FRAME
		;
		XOR	ECX,ECX
		MOV	WM_LAST_SEGMENT_GINDEX,EAX

		MOV	WM_LAST_LIN_SRC_GINDEX,ECX	;FORCE NEW CODEVIEW RECORD
		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		;
if	fg_pe
		GETT	DL,OUTPUT_PE

		OR	DL,DL
		JZ	L1$

		MOV	EDX,[EAX]._SEG_PEOBJECT_GINDEX
		MOV	EAX,[EAX]._SEG_PEOBJECT_NUMBER

		CONVERT	EDX,EDX,PE_OBJECT_GARRAY
		ASSUME	EDX:PTR PE_OBJECT_STRUCT

		MOV	ECX,[EDX]._PEOBJECT_RVA

		MOV	WM_SEG_FRAME,ECX
		JMP	L2$

L1$:
endif

		MOV	EAX,[EAX]._SEG_OS2_NUMBER
if	fg_segm
		GETT	DL,OUTPUT_SEGMENTED

		OR	DL,DL
		JNZ	L2$
endif
		MOV	WM_SEG_FRAME,EAX

		SHR	EAX,4
L2$:
		PUSH	EDI

		MOV	EDI,OFF LIN_FRAME+1
		CALL	HEXWOUT

		POP	EDI
		RET

LCSEGMENT_START	ENDP


LINE_START	PROC	NEAR	PRIVATE
		;
		;EAX IS RECORD LOGICAL
		;
		ASSUME	EAX:PTR LINNUM_HEADER_TYPE

		MOV	ECX,[EAX]._LN_BLOCK_BASE
		MOV	EDX,[EAX]._LN_NEXT_LINNUM

		MOV	WM_LN_BLOCK_BASE,ECX
		MOV	WM_BLOCK_BASE,ECX

		LEA	EBX,[ECX+PAGE_SIZE-6]

		MOV	WM_LN_NEXT_LINNUM,EDX
		MOV	ECX,DPTR [EAX]._LN_LENGTH

		MOV	EDX,[EAX]._LN_SRC_GINDEX
		MOV	DPTR WM_LN_LENGTH,ECX

		MOV	WM_LN_SRC_GINDEX,EDX
		LEA	ESI,[EAX + SIZEOF LINNUM_HEADER_TYPE]
		;
		;
		;
		MOV	AL,WM_LN_TYPE

		MOV	ECX,4
		MOV	EDX,-1

		TEST	AL,MASK BIT_32
		JNZ	L1$

		MOV	CL,2
		MOV	EDX,0FFFFH
L1$:
		MOV	OFFSET_SIZE,ECX
		MOV	OFFSET_MASK,EDX
		;
		;CHECK FOR MATCHING THEADR
		;
		MOV	ECX,WM_LAST_LIN_SRC_GINDEX
		MOV	EDX,WM_LN_SRC_GINDEX

		CMP	ECX,EDX
		JZ	L9$

		PUSH	ESI
		;
		;NEW THEADR, FLUSH LAST LINENUMBER RECORD, AND SET UP NEW
		;
		CMP	EDI,OFF XOUTBUF
		JZ	L3$
		CALL	LINE_OUT
L3$:
		MOV	EAX,OFF LINENUM_HEADER
		CALL	HEADER_OUT

		MOV	ECX,WM_CURN_FILE_LIST_GINDEX
		MOV	EAX,EDI

		push	ECX
		push	EAX
		call	_move_file_list_gindex_path_prim_ext
		add	ESP,8

		MOV	ESI,WM_LN_SRC_GINDEX
		MOV	BPTR [EAX],'('

		LEA	EDI,[EAX+1]
		MOV	WM_LAST_LIN_SRC_GINDEX,ESI

		CONVERT	ESI,ESI,SRC_GARRAY
		ADD	ESI,SRC_STRUCT._SRC_TEXT
		CALL	MOVE_ASCIZ_ESI_EDI
		;
		;GET OFFSET FIRST...
		;
		MOV	ESI,OFF SEGMENT_TEXT
		CALL	MOVE_ESI_EDI_STG

		MOV	ESI,WM_LAST_SEGMENT_GINDEX
		CONVERT	ESI,ESI,SEGMENT_GARRAY

		ADD	ESI,SEGMENT_STRUCT._SEG_TEXT
		CALL	MOVE_ASCIZ_ESI_EDI

if	any_overlays
		BITT	DOING_OVERLAYS
		JZ	8$
		LDS	SI,WM_SEGMOD
		SYM_CONV_DS
		TEST	[SI]._SM_PLTYPE,MASK LEVEL_0_SECTION
		JNZ	8$
		LDS	SI,[SI]._SM_SECTION
		SYM_CONV_DS
		CALL	OUT_SECT_NUMBER
8$:
endif
		MOV	DPTR [EDI],0A0DH
		ADD	EDI,2

		CALL	LINE_OUT
		POP	ESI			;LOCKED LINNUM RECORD
L9$:
		MOV	EAX,DPTR WM_LN_LENGTH

		MOV	DL,WM_LN_TYPE
		AND	EAX,0FFFFH

		AND	DL,MASK BIT_32
		JZ	L91$

		MOV	ECX,6
		XOR	EDX,EDX

		DIV	CX

		MOV	WM_COUNT,EAX
		TEST	EDX,EDX

		JNZ	OBJ_E
OBJ_E_RET:
		RET

L91$:
		TEST	AL,3
		JNZ	OBJ_E

		SHR	EAX,2

		MOV	WM_COUNT,EAX

		RET

OBJ_E:
		CALL	OBJ_PHASE
		JMP	OBJ_E_RET

LINE_START	ENDP


SCBTA16 	PROC	NEAR
		;
		;
		;
		MOV	ECX,'    '
		XOR	EDX,EDX

		MOV	[EDI],ECX
		MOV	[EDI+4],ECX

		ADD	EDI,6
		MOV	ECX,10

		PUSH	EDI
		DEC	EDI

		TEST	EAX,EAX
		JZ	L9$

		CMP	EAX,2550		;USE FASTEST POSSIBLE DIVIDE INSTRUCTION
		JBE	L4$
L1$:
		XOR	EDX,EDX
		DEC	EDI

		DIV	CX

		OR	DL,30H
		CMP	EAX,2550

		MOV	[EDI+1],DL
		JA	L1$
L5$:
		DIV	CL

		OR	AH,30H

		MOV	[EDI],AH
		MOV	AH,0

		DEC	EDI
L4$:
		CMP	EAX,10
		JAE	L5$

		OR	AL,30H

		MOV	[EDI],AL
L7$:
		POP	EDI

		RET

L9$:
		MOV	BPTR [EDI],'0'
		POP	EDI

		RET

SCBTA16 	ENDP


		.CONST

LINENUM_HEADER	DB	SIZEOF LINENUM_HEADER-1,0DH,0AH,\
                        'Line numbers for '

SEGMENT_TEXT	DB	SIZEOF SEGMENT_TEXT-1,') segment '
GROUP_TEXT	DB	SIZEOF GROUP_TEXT-1,') group '

WRITING_LINNUMS_MSG	DB	SIZEOF WRITING_LINNUMS_MSG-1,'Writing Line Numbers to .MAP file',0DH,0AH

if	debug

FINI_LINNUMS_MSG	DB	SIZEOF FINI_LINNUMS_MSG-1,'Line Numbers Finished',0DH,0AH

endif

		.DATA

		ALIGN	4

LIN_FRAME	DB	' FFFF:  '


		END

